package com.project.web.wechat.controller.app;

import com.project.common.core.config.prop.PropAttributes;
import com.project.common.core.config.prop.PropConfig;
import com.project.common.core.utils.DateUtil;
import com.project.common.core.utils.StringUtil;
import com.project.common.core.utils.exception.Result;
import com.project.common.core.utils.redis.RedisClient;
import com.project.common.core.utils.weChat.WeChatMpUtil;
import com.project.common.core.utils.weChat.WeChatSignUtil;
import com.project.common.core.utils.wx.message.res.TemplateMessage;
import com.project.common.core.utils.wx.message.res.TemplateMessageValue;
import com.project.web.util.exception.WeChatCustomException;
import com.project.web.util.exception.WECHAT_RESP_CODE_ENUM;
import com.project.web.wechat.controller.common.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONObject;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * 微信公众号业务控制器
 *
 * @Author: wyy
 * @Date: 2020-04-08 13:00
 */
@Api(tags = "微信公众号服务接口")
@RestController("xyWeChatMpController")
@RequestMapping("/weChat/mp")
public class WeChatMpController extends BaseController {
    public static final Logger log = LoggerFactory.getLogger(WeChatMpController.class);

    /**
     * 注入redis工具类
     */
    @Resource(name = "redisClient")
    private RedisClient redisClient;

    /**
     * 根据网页授权code换取openId
     *
     * @param code 网页授权code
     * @return
     */
    @ApiOperation(value = "根据网页授权code换取openId")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "code", value = "网页授权code", dataType = "String", required = true)
    })
    @PostMapping(value = "/getOauth2AccessToken")
    public Result<JSONObject> test(String code) {
        log.info("code:\r\n{}", code);
        if (StringUtils.isBlank(code)) {
            throw new WeChatCustomException(WECHAT_RESP_CODE_ENUM.MISS_PARAMETER);
        }
        JSONObject oauth2AccessToken = WeChatMpUtil.getOauth2AccessToken(code);
        log.info("oauth2AccessToken:\r\n{}", oauth2AccessToken.toString());
        return getResult(oauth2AccessToken);
    }

    /**
     * 根据网页授权code获取用户信息
     *
     * @param code 网页授权code
     * @return
     */
    @ApiOperation(value = "根据网页授权code换取用户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "code", value = "网页授权code", dataType = "String", required = true)
    })
    @PostMapping(value = "/getOauth2UserInfo")
    public Result<JSONObject> getOauth2UserInfo(String code) {
        // 校验参数
        log.info("code:{}", code);
        Object codeObject = redisClient.get(code);
        if (StringUtils.isBlank(code) || null != codeObject) {
            throw new WeChatCustomException(WECHAT_RESP_CODE_ENUM.MISS_WEB_AUTH_PARAMETER);
        }

        // code不为空，则设置到redis，防止二次请求
        redisClient.set(code, 1, 60);
        JSONObject oauth2AccessToken = WeChatMpUtil.getOauth2AccessToken(code);
        log.info("getOauth2UserInfo:\r\n{}", oauth2AccessToken.toString());
        if (oauth2AccessToken != null) {
            JSONObject userInfo = WeChatMpUtil.getUserInfo(oauth2AccessToken.get("access_token").toString(), oauth2AccessToken.get("openid").toString());
            log.info("getOauth2UserInfo 用户信息:\r\n{}", userInfo.toString());
            redisClient.del(code);
            return getResult(userInfo);
        }
        redisClient.del(code);
        return getResult(null);
    }

    /**
     * 根据重定向地址及state参数生成网页授权链接【静默授权】
     *
     * @param redirectUri 重定向地址
     * @param state       网页授权参数
     * @return
     */
    @ApiOperation(value = "根据重定向地址及state参数生成网页授权链接")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "redirectUri", value = "网页授权重定向地址", dataType = "String", required = true),
            @ApiImplicitParam(paramType = "query", name = "state", value = "网页授权State参数", dataType = "String", required = true)
    })
    @PostMapping(value = "/getOauth2UrlOfBase")
    public Result<String> getOauth2UrlOfBase(String redirectUri, String state) {
        String webAuthUrl = WeChatMpUtil.getOauth2UrlOfBase(state, redirectUri);
        return getResult(webAuthUrl);
    }

    /**
     * 根据重定向地址及state参数生成网页授权链接【用户确认授权】
     *
     * @param redirectUri 重定向地址
     * @param state       网页授权参数
     * @return
     */
    @ApiOperation(value = "根据重定向地址及state参数生成网页授权链接")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "redirectUri", value = "网页授权重定向地址", dataType = "String", required = true),
            @ApiImplicitParam(paramType = "query", name = "state", value = "网页授权State参数", dataType = "String", required = true)
    })
    @PostMapping(value = "/getWebAuthUrlOfUserInfo")
    public Result<String> getWebAuthUrlOfUserInfo(String redirectUri, String state) {
        String webAuthUrl = WeChatMpUtil.getWebAuthUrlOfUserInfo(state, redirectUri);
        return getResult(webAuthUrl);
    }

    /**
     * 微信发送消息模板
     *
     * @param learnBlogId  学有圈id
     * @param teacherName  老师名称
     * @param xcxUserId    用户id
     * @param xcxOpenId    微信openid
     * @param chapterTitle 章节标题
     * @return
     */
    @PostMapping(value = "/sendTemplateMsg")
    public Boolean sendTemplateMsg(String learnBlogId, String teacherName, String xcxUserId, String xcxOpenId, String chapterTitle) {
        TemplateMessage msg = new TemplateMessage();
        msg.setTouser(xcxOpenId);
        msg.setTemplate_id(PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_CARD_REVIEW_TEMPLATEID));

        TreeMap<String, String> miniProgramTreeMap = new TreeMap<>();
        miniProgramTreeMap.put("appid", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MINI_APPID));
        miniProgramTreeMap.put("pagepath", "pages/xueyouquan/aloneLearn?userId=" + xcxUserId + "&blogId=" + learnBlogId);
        msg.setMiniprogram(miniProgramTreeMap);

        Map<String, TemplateMessageValue> dataMap = new HashMap<>();
        dataMap.put("first", new TemplateMessageValue("同学你好,老师已完成点评"));
        dataMap.put("keyword1", new TemplateMessageValue(chapterTitle));
        dataMap.put("keyword2", new TemplateMessageValue(teacherName + "老师"));
        dataMap.put("keyword3", new TemplateMessageValue(DateUtil.convertDateToStr(new Date(), "yyyy-MM-dd HH:mm:ss")));
        dataMap.put("remark", new TemplateMessageValue("查看点评详情"));
        msg.setData(dataMap);

        String resultMsg = WeChatMpUtil.sendTemplateMessage(msg);
        log.info("发送模板返回信息============" + resultMsg);

        if (!StringUtil.isEmpty(resultMsg)) {
            JSONObject jsonObject = JSONObject.fromObject(resultMsg);

            return jsonObject.getInt("errcode") == 0 && "ok".equals(jsonObject.getString("errmsg"));
        }

        return false;
    }

    /**
     * 获取JSSDK-config参数
     *
     * @param request
     * @return
     */
    @GetMapping(value = "/getConfigOfJSSDK")
    public Result<Map<String, Object>> getConfigOfJSSDK(HttpServletRequest request) {
        log.info("\r\n ************ JSSDK-config ****************");
        // JSSDK签名
        Map<String, Object> jsApiMap = new TreeMap<String, Object>();
        jsApiMap.put("jsapi_ticket", WeChatMpUtil.getJsApiTicket());
        jsApiMap.put("noncestr", RandomStringUtils.randomAlphanumeric(16));
        jsApiMap.put("timestamp", System.currentTimeMillis() / 1000);
        jsApiMap.put("url", request.getRequestURL().toString() + "?" + request.getQueryString());

        // 设置视图层JS-SDK数据
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("appId", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        returnMap.put("signature", WeChatSignUtil.generateSHA1Sign(jsApiMap));
        returnMap.put("wxMap", jsApiMap);
        return getResult(returnMap);
    }

}
